#include <iostream>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "Queue.h"
#include "RequestQueue.h"
#include "ResponseQueue.h"
#include "Messages.h"
#include "TableRecord.h"
#include "OperationParser.h"
#include "Constants.h"

using namespace std;

void printHelp() {
	cout << "Comandos disponibles:" << endl;
	cout << "  - add        Agregar un registro a la tabla en la base de datos." << endl;
	cout << "      Uso:         add 'nombre' 'direccion' 'telefono'" << endl;
	cout << "      Parametros:  Los valores de cada campo del registro (en ese orden y usando comillas)." << endl;
	cout << "  - search     Buscar un registro de la tabla en la base de datos por su campo id." << endl;
	cout << "      Uso:         search id" << endl;
	cout << "      Parametros:  El id del registro que se quiere buscar." << endl;
	cout << "  - delete     Borrar un registro de la tabla en la base de datos por su campo id." << endl;
	cout << "      Uso:         delete id" << endl;
	cout << "      Parametros:  El id del registro que se quiere borrar." << endl;
	cout << "  - list       Consultar todos los registros de la tabla en la base de datos." << endl;
	cout << "      Uso:         list" << endl;
	cout << "  - exit       Salir del programa." << endl;
	cout << "      Uso:         exit" << endl << endl;
}

void init() {
	// Crea el directorio base.
	mkdir(ROOTDIRECTORY, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

	// Crea el key file para las queues.
	int fd = open(KEYFILEPATH, O_CREAT | O_WRONLY, 0644);
	close(fd);
}

void sendRequestAndReceiveResponse(RequestQueue &requestQueue, ResponseQueue &responseQueue, RequestMessage &request) {
	cout << "Enviando request por la cola de pedidos..." << endl;
	int result = requestQueue.Send(request);
	cout << "Request enviado (result: " << result << ")" << endl;

	ResponseMessage response;
	do {
		cout << "Esperando respuesta por la cola de respuestas..." << endl;
		result = responseQueue.Receive(response);
		cout << "Respuesta recibida (result: " << result << ")" << endl;

		if (response.success) {
			cout << "- Record.id: " << response.record.id << endl;
			cout << "- Record.name: " << response.record.name << endl;
			cout << "- Record.address: " << response.record.address << endl;
			cout << "- Record.phone: " << response.record.phone << endl;
		} else {
			cout << "El request no fue procesado con exito." << endl;
		}

		cout << endl;
	} while ((response.hasNext) && (result != -1));
}

int main() {
	// Inicializo los archivos requeridos.
	init();

	RequestQueue requestQueue((char*)KEYFILEPATH, REQUESTCHAR);
	ResponseQueue responseQueue((char*)KEYFILEPATH, RESPONSECHAR);

	cout << "--------------------------------" << endl;
	cout << "* Bienvenido a DataBaseClient *" << endl;
	cout << "--------------------------------" << endl;
	cout << "Por favor, ingrese la operacion a realizar." << endl;
	cout << "Ingrese 'help' para ver las operaciones disponibles." << endl << endl;

	// Loop de recepcion y parseo de operaciones del usuario.
	OperationParser parser;
	string operationString = "";
	RequestMessage request = parser.getRequest();
	while (request.operation != EXIT) {
		cout << "> ";
		getline(cin, operationString);

		if (parser.parse(operationString)) {
			request = parser.getRequest();
			if (request.operation == EXIT){
				continue;
			}

			if (request.operation == HELP) {
				printHelp();
			} else {
				sendRequestAndReceiveResponse(requestQueue, responseQueue, request);
			}
		} else {
			cout << "Operacion invalida." << endl;
			printHelp();
		}
	}

	cout << "Cerrando DataBaseClient..." << endl;

	return 0;
}
